package com.aloaproject.ciquta;

public class Restrictions {

    /**
     * Apply an "equals()" constraint to the named property.
     */
    public static final Criterion eq(final String propertyName, final Object expectedValue) {
        return new EqCriterion(propertyName, expectedValue);
    }

    /**
     * Apply an "==" constraint to the named property.
     */
    public static final Criterion eqeq(final String propertyName, final Object expectedValue) {
        return new EqEqCriterion(propertyName, expectedValue);
    }

    /**
     * Apply a "!equals()" constraint to the named property.
     */
    public static final Criterion ne(String propertyName, Object value) {
        return new GenericCriterion(
                new Matcher() {

                    public boolean test(Object referenceValue, Object actualValue) {
                        if (referenceValue == null) {
                            return referenceValue != actualValue;
                        } else {
                            return !referenceValue.equals(actualValue);
                        }
                    }
                },
                propertyName,
                value);
    }

    /**
     * Apply a "!==" constraint to the named property.
     */
    public static final Criterion neqeq(String propertyName, Object value) {
        return new GenericCriterion(
                new Matcher() {

                    public boolean test(Object referenceValue, Object actualValue) {
                        return !(referenceValue == actualValue);
                    }
                },
                propertyName,
                value);
    }

    /**
     * Apply a "greater than" constraint to the named property
     * @param propertyName property that should be Comparable
     * @param value value that should be Comparable
     */
    public static Criterion gt(String propertyName, Object value) {
        if (value == null || !(value instanceof Comparable)) {
            throw new IllegalArgumentException("value should implement " + Comparable.class.getName());
        }
        return new GenericCriterion(
                new Matcher() {

                    public boolean test(Object referenceValue, Object actualValue) {
                        if (!(actualValue instanceof Comparable)) {
                            throw new IllegalArgumentException("The value is not comparable.");
                        }
                        return ((Comparable) actualValue).compareTo(referenceValue) > 0;
                    }
                },
                propertyName,
                value);
    }

    /**
     * Apply a "less than" constraint to the named property
     * @param propertyName property that should be Comparable
     * @param value value that should be Comparable
     */
    public static Criterion lt(String propertyName, Comparable value) {
        if (value == null || !(value instanceof Comparable)) {
            throw new IllegalArgumentException("value should implement " + Comparable.class.getName());
        }
        return new GenericCriterion(
                new Matcher() {

                    public boolean test(Object referenceValue, Object actualValue) {
                        if (!(actualValue instanceof Comparable)) {
                            throw new IllegalArgumentException("The value is not comparable.");
                        }
                        return ((Comparable) actualValue).compareTo(referenceValue) < 0;
                    }
                },
                propertyName,
                value);
    }

    /**
     * Apply a "less or equal than" constraint to the named property
     * @param propertyName property that should be Comparable
     * @param value value that should be Comparable
     */
    public static Criterion le(String propertyName, Comparable value) {
        if (value == null || !(value instanceof Comparable)) {
            throw new IllegalArgumentException("value should implement " + Comparable.class.getName());
        }
        return new GenericCriterion(
                new Matcher() {

                    public boolean test(Object referenceValue, Object actualValue) {
                        if (!(actualValue instanceof Comparable)) {
                            throw new IllegalArgumentException("The value is not comparable.");
                        }
                        return ((Comparable) actualValue).compareTo(referenceValue) <= 0;
                    }
                },
                propertyName,
                value);
    }

    /**
     * Apply a "greater or equal than" constraint to the named property
     * @param propertyName property that should be Comparable
     * @param value value that should be Comparable
     */
    public static Criterion ge(String propertyName, Comparable value) {
        if (value == null || !(value instanceof Comparable)) {
            throw new IllegalArgumentException("value should implement " + Comparable.class.getName());
        }
        return new GenericCriterion(
                new Matcher() {

                    public boolean test(Object referenceValue, Object actualValue) {
                        if (!(actualValue instanceof Comparable)) {
                            throw new IllegalArgumentException("The value is not comparable.");
                        }
                        return ((Comparable) actualValue).compareTo(referenceValue) >= 0;
                    }
                },
                propertyName,
                value);
    }

    /**
     * Apply a "like" constraint to the named property.
     */
    public static Criterion like(String propertyName, String referenceValue) {
        return new GenericCriterion(
                new Matcher() {

                    public boolean test(final Object referenceValue, final Object actualValue) {

                        String regEx = referenceValue.toString();
                        regEx.replace("%", "\\.{0,}");
                        regEx.replace("_", "\\.");

                        boolean result;
                        if(actualValue != null){
                            result = actualValue.toString().matches(regEx);
                        }else{
                            result = false;
                        }

                        return result;
                    }
                },
                propertyName,
                referenceValue);
    }

    /**
     * Apply a case insensitive "like" constraint to the named property.
     * This method mock the SQL like notation, so % substitutes a set of char
     * and _ a signle char.
     */
    public static Criterion ilike(String propertyName, String referenceValue) {
        return new GenericCriterion(
                new Matcher() {

                    public boolean test(final Object referenceValue, final Object actualValue) {

                        String regEx = referenceValue.toString().toLowerCase();
                        regEx.replace("%", "\\.{0,}");
                        regEx.replace("_", "\\.");

                        boolean result;
                        if(actualValue != null){
                            result = actualValue.toString().toLowerCase().matches(regEx);
                        }else{
                            result = false;
                        }

                        return result;
                    }
                },
                propertyName,
                referenceValue);
    }

    /**
     * Apply a case insensitive "like" constraint to the named property.
     */
    public static Criterion isNull(String propertyName, String referenceValue) {
        return eqeq(propertyName, null);
    }

    /**
     * Invert the valifity of a criterion.
     */
    public static Criterion not(final Criterion criterion){
        return new NotCriterion(criterion);
    }

    /**
     * Returns the conjunction of a number of expression.
     * @param criterions
     * @return
     */
    public static final Criterion and(final Criterion... criterions) {
        return new AndCriterion(criterions);
    }

    /**
     * Returns the disjunction of a number of expression.
     * @param criterions
     * @return
     */
    public static final Criterion or(final Criterion... criterions) {
        return new OrCriterion(criterions);
    }

//========================================================
// This is the list of method contained in Hibernate Criteria
// Please, use them as reference and when a method is implemented remove it from the list.
//========================================================
//26     /**
//27      * Apply an "equal" constraint to the identifier property
//28      * @param propertyName
//29      * @param value
//30      * @return Criterion
//31      */
//32     public static Criterion eqeq(Object JavaDoc value) {
//33         return new IdentifierEqExpression(value);
//34     }
//53     /**
//54      * Apply a "like" constraint to the named property
//55      * @param propertyName
//56      * @param value
//57      * @return Criterion
//58      */
//59     public static SimpleExpression like(String JavaDoc propertyName, Object JavaDoc value) {
//60         return new SimpleExpression(propertyName, value, " like ");
//61     }



//129     /**
//130      * Apply a "between" constraint to the named property
//131      * @param propertyName
//132      * @param lo value
//133      * @param hi value
//134      * @return Criterion
//135      */
//136     public static Criterion between(String JavaDoc propertyName, Object JavaDoc lo, Object JavaDoc hi) {
//137         return new BetweenExpression(propertyName, lo, hi);
//138     }
//139     /**
//140      * Apply an "in" constraint to the named property
//141      * @param propertyName
//142      * @param values
//143      * @return Criterion
//144      */
//145     public static Criterion in(String JavaDoc propertyName, Object JavaDoc[] values) {
//146         return new InExpression(propertyName, values);
//147     }
//148     /**
//149      * Apply an "in" constraint to the named property
//150      * @param propertyName
//151      * @param values
//152      * @return Criterion
//153      */
//154     public static Criterion in(String JavaDoc propertyName, Collection JavaDoc values) {
//155         return new InExpression( propertyName, values.toArray() );
//156     }
//164     /**
//165      * Apply an "equal" constraint to two properties
//166      */
//167     public static PropertyExpression eqProperty(String JavaDoc propertyName, String JavaDoc otherPropertyName) {
//168         return new PropertyExpression(propertyName, otherPropertyName, "=");
//169     }
//170     /**
//171      * Apply a "not equal" constraint to two properties
//172      */
//173     public static PropertyExpression neProperty(String JavaDoc propertyName, String JavaDoc otherPropertyName) {
//174         return new PropertyExpression(propertyName, otherPropertyName, "<>");
//175     }
//176     /**
//177      * Apply a "less than" constraint to two properties
//178      */
//179     public static PropertyExpression ltProperty(String JavaDoc propertyName, String JavaDoc otherPropertyName) {
//180         return new PropertyExpression(propertyName, otherPropertyName, "<");
//181     }
//182     /**
//183      * Apply a "less than or equal" constraint to two properties
//184      */
//185     public static PropertyExpression leProperty(String JavaDoc propertyName, String JavaDoc otherPropertyName) {
//186         return new PropertyExpression(propertyName, otherPropertyName, "<=");
//187     }
//188     /**
//189      * Apply a "greater than" constraint to two properties
//190      */
//191     public static PropertyExpression gtProperty(String JavaDoc propertyName, String JavaDoc otherPropertyName) {
//192         return new PropertyExpression(propertyName, otherPropertyName, ">");
//193     }
//194     /**
//195      * Apply a "greater than or equal" constraint to two properties
//196      */
//197     public static PropertyExpression geProperty(String JavaDoc propertyName, String JavaDoc otherPropertyName) {
//198         return new PropertyExpression(propertyName, otherPropertyName, ">=");
//199     }
//272
//273     /**
//274      * Group expressions together in a single conjunction (A and B and C...)
//275      *
//276      * @return Conjunction
//277      */
//278     public static Conjunction conjunction() {
//279         return new Conjunction();
//280     }
//281
//282     /**
//283      * Group expressions together in a single disjunction (A or B or C...)
//284      *
//285      * @return Conjunction
//286      */
//287     public static Disjunction disjunction() {
//288         return new Disjunction();
//289     }
//290
//291     /**
//292      * Apply an "equals" constraint to each property in the
//293      * key set of a <tt>Map</tt>
//294      *
//295      * @param propertyNameValues a map from property names to values
//296      * @return Criterion
//297      */
//298     public static Criterion allEq(Map JavaDoc propertyNameValues) {
//299         Conjunction conj = conjunction();
//300         Iterator JavaDoc iter = propertyNameValues.entrySet().iterator();
//301         while ( iter.hasNext() ) {
//302             Map.Entry JavaDoc me = (Map.Entry JavaDoc) iter.next();
//303             conj.add( eq( (String JavaDoc) me.getKey(), me.getValue() ) );
//304         }
//305         return conj;
//306     }
//307
//308     /**
//309      * Constrain a collection valued property to be empty
//310      */
//311     public static Criterion isEmpty(String JavaDoc propertyName) {
//312         return new EmptyExpression(propertyName);
//313     }
//314
//315     /**
//316      * Constrain a collection valued property to be non-empty
//317      */
//318     public static Criterion isNotEmpty(String JavaDoc propertyName) {
//319         return new NotEmptyExpression(propertyName);
//320     }
//321
//322     /**
//323      * Constrain a collection valued property by size
//324      */
//325     public static Criterion sizeEq(String JavaDoc propertyName, int size) {
//326         return new SizeExpression(propertyName, size);
//327     }
//328
//329     public static NaturalIdentifier naturalId() {
//330         return new NaturalIdentifier();
//331     }
//332
//333 }
}
